import torch
import torch.nn as nn
import torch.optim as optim

# 定义一个简单的神经网络模型
class SimpleNet(nn.Module):
    def __init__(self):
        super(SimpleNet, self).__init__()
        self.fc1 = nn.Linear(10, 20)
        self.relu = nn.ReLU()
        self.fc2 = nn.Linear(20, 1)

    def forward(self, x):
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        return x

# 创建模型实例
model = SimpleNet()

# 定义一个函数来设置模型参数的 requires_grad 属性
def requires_grad(model, value):
    for param in model.parameters():
        param.requires_grad = value

# 打印模型各层参数的 requires_grad 属性初始值
print("初始状态：")
for name, param in model.named_parameters():
    print(f"{name}: {param.requires_grad}")

# 将模型的所有参数的 requires_grad 属性设置为 False
requires_grad(model, True)

# 打印修改后模型各层参数的 requires_grad 属性
print("\n将所有参数的 requires_grad 属性设置为 False 后：")
for name, param in model.named_parameters():
    print(f"{name}: {param.requires_grad}")

# 定义输入数据和目标数据
input_data = torch.randn(1, 10)
target = torch.randn(1, 1)

# 定义损失函数和优化器
criterion = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)

# 前向传播
output = model(input_data)
loss = criterion(output, target)

# 反向传播
loss.backward()

# 打印反向传播后模型各层参数的梯度
print("\n反向传播后各层参数的梯度：")
for name, param in model.named_parameters():
    print(f"{name} 的梯度: {param.grad}")

# 将模型的所有参数的 requires_grad 属性设置为 True
requires_grad(model, True)

# 再次进行前向传播和反向传播
output = model(input_data)
loss = criterion(output, target)
loss.backward()

# 打印再次反向传播后模型各层参数的梯度
print("\n再次将所有参数的 requires_grad 属性设置为 True 后，反向传播后各层参数的梯度：")
for name, param in model.named_parameters():
    print(f"{name} 的梯度: {param.grad}")